home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccwossrc.lha / vbcc / pasm / output_ehf.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  12KB  |  416 lines

  1. /* $VER: pasm output_ehf.c V1.2 (24.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (24.10.98) phx
  16.  *        An empty section with reloc symbols will no longer be deleted.
  17.  *        Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
  18.  * v1.1d  (27.09.98) phx
  19.  *        fopen() uses binary mode "b" for windoze/msdog compatibility.
  20.  * v1.1b  (05.07.98) phx
  21.  *        Support for Chip/Fast-Ram sections (new .section-attributes
  22.  *        "C" and "F").
  23.  * v1.0   (02.05.98) phx
  24.  *        Empty EHF objects contain at least an empty CODE-hunk.
  25.  * v0.9   (24.03.98) phx
  26.  *        XDef for global symbols with type = @object was missing.
  27.  *        Use the name set by ".file" for the unit name and not the
  28.  *        one set by ".ident", which has no meaning for EHF.
  29.  * v0.7   (02.01.98) phx
  30.  *        Sections after a section with HUNK_EXT were 4 bytes too large.
  31.  *        Output format OFMT_ADOS support. The difference between ADOS and
  32.  *        and EHF is, that ADOS uses HUNK_CODE instead HUNK_PPC_CODE and
  33.  *        doesn't support any PPC-specific relocations and references types.
  34.  *        This makes it possible to link simple PowerPC programs with an
  35.  *        old linker, like BLink, SLink or PhxLnk.
  36.  * v0.4   (02.07.97) phx
  37.  *        File created.
  38.  */
  39.  
  40.  
  41. #define OUTPUT_EHF_C
  42. #include "ppcasm.h"
  43. #include "ehf.h"
  44.  
  45.  
  46. struct XRefNode {
  47.   struct node n;
  48.   char *sym_name;
  49.   uint8 ref_type;
  50.   int noffsets;
  51.   struct list xreflist;
  52. };
  53.  
  54.  
  55. static char *output_name;
  56. static int nsecs = 0;
  57. static bool exthunk;
  58.  
  59.  
  60. void output_ehf(struct GlobalVars *);
  61.  
  62. static void reloc_hunk(FILE *,struct Section *,uint8,uint32);
  63. static void unsupp_relocs(struct Section *);
  64. static void ext_header(FILE *);
  65. static void ext_refs(FILE *,struct GlobalVars *,struct Section *);
  66. static void ext_defs(FILE *,struct GlobalVars *,uint32,uint8,uint32);
  67. static uint32 word_strlen(char *);
  68. static void write_name(FILE *,struct GlobalVars *,char *);
  69. static void fwalign(FILE *,struct GlobalVars *,uint32);
  70. static void fw(FILE *,void *,size_t);
  71. static void fw4(FILE *,uint32);
  72.  
  73.  
  74.  
  75. void output_ehf(struct GlobalVars *gv)
  76. {
  77.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  78.   struct Symbol *symchain;
  79.   uint32 index;
  80.   bool ehfmode = gv->output==OFMT_EHF;
  81.   bool empty = TRUE;
  82.   FILE *fp;
  83.  
  84.   /* assign an index to each valid section */
  85.   while (nextsec = (struct Section *)sec->n.next) {
  86.     if (!(sec->flags & SF_DISCARD) && sec->size > 0)
  87.       sec->index = nsecs++;
  88.     sec = nextsec;
  89.   }
  90.  
  91.   /* create output file */
  92.   output_name = gv->dest_name;
  93.  
  94.   if (fp = fopen(output_name,"wb")) {  /* create output file */
  95.     fw4(fp,HUNK_UNIT);
  96.     if (gv->file) {
  97.       fw4(fp,word_strlen(gv->file));  /* unit name */
  98.       write_name(fp,gv,gv->file);
  99.     }
  100.     else
  101.       fw4(fp,0);
  102.  
  103.  
  104.     /* section loop */
  105.     sec = (struct Section *)gv->sectionlist.first;
  106.     while (nextsec = (struct Section *)sec->n.next) {
  107.       exthunk = FALSE;
  108.       if (!(sec->flags & SF_DISCARD) &&
  109.           (sec->size > 0 || (sec->flags & SF_HASSYMS))) {
  110.         uint32 styp = HUNK_DATA;  /* default type */
  111.  
  112.         index = sec->index;
  113.         empty = FALSE;
  114.  
  115.         /* section name */
  116.         fw4(fp,HUNK_NAME);
  117.         fw4(fp,word_strlen(sec->name));
  118.         write_name(fp,gv,sec->name);
  119.  
  120.         /* section type and size */
  121.         switch(sec->type) {
  122.           case ST_CODE:
  123.             styp = ehfmode ? HUNK_PPC_CODE : HUNK_CODE;
  124.             break;
  125.           case ST_DATA:
  126.             styp = HUNK_DATA;
  127.             break;
  128.           case ST_UDATA:
  129.             styp = HUNK_BSS;
  130.             break;
  131.           default:  /* section type not supported in EHF/ADOS */
  132.             error(52,sec->name,(int)sec->type);
  133.             break;
  134.         }
  135.  
  136.         if (sec->flags & SF_CHIP)
  137.           styp |= HUNKF_CHIP;
  138.         else if (sec->flags & SF_FAST)
  139.           styp |= HUNKF_FAST;
  140.         fw4(fp,styp);
  141.         fw4(fp,(uint32)(sec->size+3)>>2);
  142.  
  143.         /* write section contents */
  144.         if (!(sec->flags & SF_UNINITIALIZED)) {
  145.           fw(fp,sec->contents,(uint32)sec->size);
  146.           fwalign(fp,gv,(uint32)sec->size);
  147.         }
  148.  
  149.         /* relocation hunks */
  150.         reloc_hunk(fp,sec,R_PPC_ADDR32,HUNK_ABSRELOC32);
  151. /* @@@  reloc_hunk(fp,sec,R_PPC_ADDR16,HUNK_ABSRELOC16); */
  152.         if (ehfmode)
  153.           reloc_hunk(fp,sec,R_PPC_REL24,HUNK_RELRELOC26);
  154.         reloc_hunk(fp,sec,R_PPC_REL14,HUNK_RELRELOC16);
  155.         reloc_hunk(fp,sec,R_PPC_REL14_BRTAKEN,HUNK_RELRELOC16);
  156.         reloc_hunk(fp,sec,R_PPC_REL14_BRNTAKEN,HUNK_RELRELOC16);
  157.         reloc_hunk(fp,sec,R_PPC_REL32,HUNK_RELRELOC32);
  158.         reloc_hunk(fp,sec,R_PPC_SDAREL16,HUNK_DREL16);
  159.         unsupp_relocs(sec);  /* print unsupported relocations */
  160.  
  161.         /* external references and global definitions */
  162.         ext_refs(fp,gv,sec);
  163.         ext_defs(fp,gv,index,SYM_RELOC,EXT_DEF);
  164.         if (index == 0)  /* put absolute definitions in first HUNK_EXT */
  165.           ext_defs(fp,gv,0xffff,SYM_ABS,EXT_ABS);
  166.         if (exthunk)
  167.           fw4(fp,0);  /* close HUNK_EXT block */
  168.  
  169.         /* symbol table */
  170.         ext_defs(fp,gv,index,SYM_RELOC,EXT_SYMB);
  171.  
  172.         fw4(fp,HUNK_END);  /* end of this hunk */
  173.       }
  174.       sec = nextsec;
  175.     }
  176.  
  177.     if (empty) {              /* there was not a single section */
  178.       fw4(fp,ehfmode ? HUNK_PPC_CODE : HUNK_CODE);
  179.       fw4(fp,0);
  180.       fw4(fp,HUNK_END);
  181.     }
  182.     fclose(fp);
  183.   }
  184.   else
  185.     error(25,output_name);  /* unable to create output file */
  186. }
  187.  
  188.  
  189. static void reloc_hunk(FILE *fp,struct Section *sec,uint8 r,uint32 ehfrel)
  190. /* generate an EHF relocation hunk for a specific reloc type */
  191. {
  192.   struct Reloc *nextrel,*rel=(struct Reloc *)sec->reloclist.first;
  193.   struct list **rlist=alloc(nsecs*sizeof(struct list *));
  194.   int *rcnt=alloczero(nsecs*sizeof(int));  /* reloc cnt for all sections */
  195.   bool hunk_required=FALSE;
  196.   int i;
  197.  
  198.   for (i=0; i<nsecs; i++) {  /* empty reloc lists for each section */
  199.     rlist[i] = alloc(sizeof(struct list));
  200.     initlist(rlist[i]);
  201.   }
  202.  
  203.   while (nextrel = (struct Reloc *)rel->n.next) {
  204.     if (rel->type == r) {
  205.       /* move reloc node of correct type into relocssect's rlist */
  206.       remnode(&rel->n);
  207.       addtail(rlist[rel->relocsect->index],&rel->n);
  208.       rcnt[rel->relocsect->index]++;
  209.       hunk_required = TRUE;
  210.     }
  211.     rel = nextrel;
  212.   }
  213.  
  214.   if (hunk_required) {  /* there's at least one relocation */
  215.     fw4(fp,ehfrel);  /* reloc hunk id */
  216.     for (i=0; i<nsecs; i++) {
  217.       if (rcnt[i]) {
  218.         fw4(fp,(uint32)rcnt[i]);  /* number of relocations */
  219.         fw4(fp,(uint32)i);  /* section index */
  220.  
  221.         /* store relocation offsets */
  222.         while(rel = (struct Reloc *)remhead(rlist[i])) {
  223.           fw4(fp,(uint32)rel->offset);
  224.           free(rel);
  225.         }
  226.       }
  227.     }
  228.     fw4(fp,0);  /* no more relocation entries */
  229.   }
  230.  
  231.   /* free dynamically allocated rlists and rcnt array */
  232.   for (i=0; i<nsecs; free(rlist[i++]));
  233.   free(rcnt);
  234. }
  235.  
  236.  
  237. static void unsupp_relocs(struct Section *sec)
  238. {
  239.   struct Reloc *nextrel,*rel=(struct Reloc *)sec->reloclist.first;
  240.  
  241.   while (nextrel = (struct Reloc *)rel->n.next) {
  242.     error(53,elfrel_name[rel->type & ELFRELNAMMSK],rel->offset,sec->name);
  243.     rel = nextrel;
  244.   }
  245. }
  246.  
  247.  
  248. static void ext_header(FILE *fp)
  249. {
  250.   if (!exthunk) {
  251.     exthunk = TRUE;
  252.     fw4(fp,HUNK_EXT);
  253.   }
  254. }
  255.  
  256.  
  257. static void ext_refs(FILE *fp,struct GlobalVars *gv,struct Section *sec)
  258. {
  259.   struct list xnodelist;  /* xrefs with same ref. type and symbol name */
  260.   struct XRefNode *xn,*nextxn;
  261.   struct XReference *xref;
  262.  
  263.   initlist(&xnodelist);
  264.   while (xref = (struct XReference *)remhead(&sec->xreflist)) {
  265.     char *name = xref->xsymbol->name;  /* name of xref'ed symbol */
  266.     uint8 rtype = xref->type;
  267.  
  268.     /* ELF32 -> EHF referen